﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Djs.Neuronic.Medium;
using Djs.Neuronic.UI.Interactive;

namespace Djs.Neuronic.UI
{
    public class DialogPanel : InteractivePanel
    {
        #region Konstrukce
        public DialogPanel()
        {
            this.Initialize();
            this.CurentPage = DialogSetSamples.CreateSet1().MainPage;
        }
        private void Initialize()
        {
            _CloseButton = new IntButton()
            { 
                ImageNormal = PicLibrary.CrossPink_Cached, ImageHot=PicLibrary.CrossYellow_Cached, ImageDown = PicLibrary.CrossRed_Cached, 
                Anchor = AnchorStyles.Right | AnchorStyles.Top, Alignment = ContentAlignment.MiddleCenter
            };
            _Image = new IntImage()
            {
                Alignment = ContentAlignment.MiddleCenter,
                Anchor = AnchorStyles.Right | AnchorStyles.Top
            };
            _PrevButton = new IntButton()
            { 
                ImageNormal = PicLibrary.LeftBlue_Cached, ImageHot=PicLibrary.LeftYellow_Cached, ImageDown = PicLibrary.LeftRed_Cached, 
                Anchor = AnchorStyles.Left | AnchorStyles.Bottom, Alignment = ContentAlignment.MiddleCenter
            };
            _Progress = new IntTimer()
            {
                BackColor = Color.LightYellow,
                Anchor = AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right
            };
            _NextButton = new IntButton()
            { 
                ImageNormal = PicLibrary.RightBlue_Cached, ImageHot=PicLibrary.RightYellow_Cached, ImageDown = PicLibrary.RightRed_Cached, 
                Anchor = AnchorStyles.Right | AnchorStyles.Bottom, Alignment = ContentAlignment.MiddleCenter
            };

            this.IntDesktop.AddChilds(_CloseButton, _Image, _PrevButton, _Progress, _NextButton);
            this.Size = new Size(460, 320);
            this._CloseButton.Bound = new Rectangle(409, 15, 36, 36);
            this._CloseButton.MouseClick += new InteractiveMouseHandler(_CloseButton_MouseClick);
            this._Image.Bound = new Rectangle(409, 66, 36, 52);
            this._PrevButton.Bound = new Rectangle(15, 269, 36, 36);
            this._PrevButton.MouseClick += new InteractiveMouseHandler(_PrevButton_MouseClick);
            this._Progress.Bound = new Rectangle(54, 279, 352, 16);
            this._Progress.TimeElapsed += new EventHandler(_Progress_TimeElapsed);
            this._Progress.Visible = false;
            this._NextButton.Bound = new Rectangle(409, 269, 36, 36);
            this._NextButton.MouseClick += new InteractiveMouseHandler(_NextButton_MouseClick);

            this.LabelFont = new Font(SystemFonts.DefaultFont.Name, 11, FontStyle.Bold);
            this._TimeOutTimer = new System.Threading.Timer(this._TimeOutTimerTick, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
        }
        IntLabel _Label;
        IntButton _CloseButton;
        IntImage _Image;
        IntButton _PrevButton;
        IntTimer _Progress;
        IntButton _NextButton;
        #endregion
        #region PageInfo

        public DialogPageInfo CurentPage
        {
            get { return this._CurentPage; }
            set { this._ShowPage(value); }
        }
        /// <summary>
        /// Zajistí zobrazení informací z dané stránky
        /// </summary>
        /// <param name="page"></param>
        private void _ShowPage(DialogPageInfo page)
        {
            this._CurentPage = page;

            if (this._Label != null && this._Label.Visible)
                this._Label.AnimateToLow((this._LabelTimeOff.HasValue ? this._LabelTimeOff.Value : 1d), Color.FromArgb(0, this.IntDesktop.BackColor), AnimateAutoLowMode.Remove);

            // Background:
            DialogBackground background = page.CurrentBackground;
            if (background != null)
            {
                if (background.BackBrushGenerator != null)
                    this.IntDesktop.BackBrushGenerator = background.BackBrushGenerator;
                if (background.BackColor.HasValue)
                    this.IntDesktop.BackColor = background.BackColor.Value;
            }

            // Label:
            DialogLabelInfo label = page.Label;
            if (label != null)
            {
                this._Label = new IntLabel() { Text = label.Text, ColorLow = Color.Transparent, ColorHigh = label.TextColor };
                this.IntDesktop.AddChild(_Label);
                Size size = this.IntDesktop.Bound.Size;
                this._Label.Bound = new Rectangle(15, 15, size.Width - 66, size.Height - 66);
                this._Label.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;
                
                Font font = label.CurrentTextFont;
                if (font == null)
                    font = this.LabelFont;
                this._Label.Font = font;
                this._Label.AnimateToHigh(label.TimeOn.HasValue ? label.TimeOn.Value : 0.1d);
            }

            // Input pole:

            // Buttony:
            this._CloseButton.Visible = this._IsVisibleForAction(page.ButtonExitAction);
            this._PrevButton.Visible = this._IsVisibleForAction(page.ButtonPrevAction);
            this._NextButton.Visible = this._IsVisibleForAction(page.ButtonNextAction);

            // Timeout:
            if (page.TimeOut.HasValue && page.TimeOutAction != null)
            {
                this._TimeOutAction = page.TimeOutAction;
                double timeOut = page.TimeOut.Value;
                if (timeOut < _TIME_VISIBLE_PART)
                    this._TimerShowDownTimer(timeOut);
                else
                    this._TimeOutTimerStart(timeOut - _TIME_VISIBLE_PART, _TimerActionType.ShowDownTimer);
            }

            this.Refresh();
        }

        private bool _IsVisibleForAction(DialogActionInfo actionInfo)
        {
            if (actionInfo == null) return false;
            return (actionInfo.ActionType != DialogActionType.None);
        }
        void _NextButton_MouseClick(object sender, InteractiveMouseArgs args)
        {
            this._ExecAction(this._CurentPage.ButtonNextAction);
        }
        void _PrevButton_MouseClick(object sender, InteractiveMouseArgs args)
        {
            this._ExecAction(this._CurentPage.ButtonPrevAction);
        }
        void _CloseButton_MouseClick(object sender, InteractiveMouseArgs args)
        {
            this._ExecAction(this._CurentPage.ButtonExitAction);
        }
        private const double _TIME_VISIBLE_PART = 5d;
        void _TimeOutTimerStart(double seconds, _TimerActionType timerAction)
        {
            this._TimerAction = timerAction;
            this._TimeOutTimer.Change(TimeSpan.FromSeconds(seconds), TimeSpan.FromMilliseconds(-1));
        }
        void _TimeOutTimerStop()
        {
            this._TimeOutTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
        }
        void _TimeOutTimerTick(object data)
        {
            this._TimeOutTimerStop();
            switch (this._TimerAction)
            {
                case _TimerActionType.ShowDownTimer:
                    this._TimerShowDownTimer(_TIME_VISIBLE_PART);
                    break;
            }
        }
        private void _TimerShowDownTimer(double seconds)
        {
            this._Progress.Value = 0.0d;
            this._Progress.AnimateTime = seconds;
            this._Progress.AnimateMode = AnimateMode.UpSinusAD;
            this._Progress.Visible = true;
        }
        void _Progress_TimeElapsed(object sender, EventArgs e)
        {
            this._Progress.Visible = false;
            this._CloseForm(false);
        }
        private _TimerActionType _TimerAction;
        private DialogActionInfo _TimeOutAction;
        private enum _TimerActionType
        {
            None,
            ShowDownTimer
        }
        private void _ExecAction(DialogActionInfo actionInfo)
        {
            if (actionInfo == null) return;
            DialogPageInfo newPage;
            switch (actionInfo.ActionType)
            {
                case DialogActionType.None:
                    break;
                case DialogActionType.CallHandler:
                    DialogActionArgs args = new DialogActionArgs(actionInfo);
                    actionInfo.SendTo(this, args);
                    if (args.NewAction != null)
                        this._ExecAction(args.NewAction);
                    break;
                case DialogActionType.GoToPage:
                    newPage = this._CurentPage.Owner.GetPage(actionInfo);
                    if (newPage != null)
                        this.CurentPage = newPage;
                    break;
                case DialogActionType.InputTextAction:
                    break;
                case DialogActionType.GoToPrevPage:
                    newPage = actionInfo.Owner.PrevPage;
                    if (newPage != null)
                        this.CurentPage = newPage;
                    break;
                case DialogActionType.GoToEndPage:
                    newPage = this._CurentPage.Owner.EndPage;
                    if (newPage != null)
                        this.CurentPage = newPage;
                    else
                        this._CloseForm(true);
                    break;

                case DialogActionType.ApplicationExit:
                    this._CloseForm(true);
                    break;
                case DialogActionType.ApplicationExitNoQuerry:
                    this._CloseForm(false);
                    break;
            }
        }
        /// <summary>
        /// Zavře formulář (volitelně s dotazem)
        /// </summary>
        /// <param name="withQuestion"></param>
        private void _CloseForm(bool withQuestion)
        {
            Form ownerForm = this.FindForm();
            bool close = true;
            if (withQuestion)
            {
                DialogResult result = MessageBox.Show(ownerForm, "Ukončit dialog?", "Poslední otázka zní...", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                close = (result == DialogResult.Yes);
            }
            if (!close) return;
            if (ownerForm == null)
                Application.Exit();
            else
                ownerForm.Close();
        }
        private DialogPageInfo _CurentPage;
        private double? _LabelTimeOff;
        private System.Threading.Timer _TimeOutTimer;
        #endregion
        public Font LabelFont { get; set; }
    }
}
